#ifndef ARBOL_H
#define ARBOL_H

#include <stdbool.h>
#include <stddef.h>

/* *****************************************************************
 *                DEFINICION DE LOS TIPOS DE DATOS
 * *****************************************************************/

typedef struct abb abb_t;
typedef int (*abb_comparar_clave_t) (const char *, const char *);
typedef void (*abb_destruir_dato_t) (void *);
typedef struct abb_iter abb_iter_t;

/* *****************************************************************
 *                    PRIMITIVAS DEL ARBOL
 * *****************************************************************/
					 /*Primitivas básicas*/
// Crea un arbol.
// Post: devuelve un nuevo arbol vacío.					 
abb_t* abb_crear(abb_comparar_clave_t cmp, abb_destruir_dato_t destruir_dato);

// Guarda un nuevo elemento en el arbol (clave y dato) si es que la clave no existe 
// en el arbol, de existir modifica el valor que tenia relacionado. 
// Pre: El arbol fue creado.
// Post: Devuelve un booleano segun si se pudo o no guardar el elemento.
bool abb_guardar(abb_t *arbol, const char *clave, void *dato);

// Borra el elemento del arbol, si es que este pertenecia, de no existir 
// el elemento de dicha clave devuelve NULL
// Pre: El arbol fue creado.
// Post: Devuelve el valor relacionado a la clave que se borro del arbol o NULL en caso de 
// que no exista la clave.
void *abb_borrar(abb_t *arbol, const char *clave);

// Devuelve el valor almacenado junto con la clave que recibe en caso de que esta pertenesca
// a los elementos del arbol.
// Pre: El arbol fue creado.
// Post: Devuelve el valor relacionado a la clave, en caso de que exista sino devuelve NULL
void *abb_obtener(const abb_t *arbol, const char *clave);

// Devuelve un booleano verdadero en caso de que la clave se encuntre almacenada en el arbol
// y falso en caso contrario.
// Pre: El arbol fue creado
// Post: Devuelve un boleano segun se encuentre o no la clave
bool abb_pertenece(const abb_t *arbol, const char *clave);

// Devuelve la cantidad de elemetos almacenados que posee en arbol.
// Pre: el arbol fue creado.
size_t abb_cantidad(abb_t *arbol);

// Destruye el arbol. Si el arbol tiene la función destruir_dato por parámetro,
// para cada uno de los valores de los elementos almacenados llama a destruir_dato.
// Pre: el arbol fue creado. destruir_dato es una función capaz de destruir
// los valores de los elementos del arbol, o NULL en caso de que no se la utilice.
// Post: se eliminaron todos los elementos del arbol y este se destruye.
void abb_destruir(abb_t *arbol);

					 /*Primitivas de iteración*/
// Aplica la funcion pasada por paramtro a todos los elementos del arbol en in orden.
// Pre: El arbol fue creado	
// Post: Se le aplica la funcion a todos los elementos almacenados en el arbol (clave y valor).			 
void abb_in_order(abb_t *arbol, bool funcion(const char *, void *, void *), void *extra);

// Crea un iterador del arbol, que lo recorre en in orden.
// Pre: El arbol fue creado. 
// Post: devuelve un iterador, apuntando al primer elemento del arbol, en dicho recorrido.	 
abb_iter_t *abb_iter_in_crear(const abb_t *arbol);

// Avanza el iterador al siguiente elemento del arbol. En caso de error devuelve false.
// Pre: el iterador y el arbol fueron creados.
// Post: devuelve un booleano si pudo o no avanzar el iterador.
bool abb_iter_in_avanzar(abb_iter_t *iter);

// Devuelve la clave al que esta apuntando el iterador. Si el iterador esta en el final del arbol
// devuelve NULL.
// Pre: el iterador y el arbol  fueron creados.
// Post: Devuelve el dato al que apuntaba el iterador o NULL.
const char *abb_iter_in_ver_actual(const abb_iter_t *iter);

// Devuelve true o false si el iterador se encuantra al final o no del arbol.
// Pre: el iterador y el arbol fueron creados.
// Post: devuelve un booleano segun donde se encuentre el iterador.
bool abb_iter_in_al_final(const abb_iter_t *iter);

// Destruye el iterador.
// Pre: el iterador fue creado.
void abb_iter_in_destruir(abb_iter_t* iter);

#endif // ARBOL_H


